package org.hepeng.fabric.gateway.pool.channel;

import io.grpc.Channel;
import io.grpc.ManagedChannel;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
import org.hyperledger.fabric.client.identity.Identities;

import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author he peng
 * @date 2022/3/24
 */
public abstract class GRpcChannels {

    private static final Map<String , ManagedChannel> CHANNEL_CACHE = new ConcurrentHashMap<>();

    public static synchronized Channel getChannel(GRpcChannelProperties properties) {

        ManagedChannel channel;
        if (CHANNEL_CACHE.containsKey(properties.getEndpoint())) {
            channel = CHANNEL_CACHE.get(properties.getEndpoint());
        } else {
            channel = newChannel(properties);
            CHANNEL_CACHE.put(properties.getEndpoint() , channel);

            Runtime.getRuntime().addShutdownHook(new Thread(channel::shutdownNow));
        }

        return channel;
    }

    private static ManagedChannel newChannel(GRpcChannelProperties properties) {

        try {
            X509Certificate tlsCert = Identities.readX509Certificate(properties.getTlsCertPem());
            return NettyChannelBuilder.forTarget(properties.getEndpoint())
                    .sslContext(GrpcSslContexts.forClient().trustManager(tlsCert).build())
                    .overrideAuthority(properties.getOverrideAuthority())
                    .build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
